
package com.x52im.mall.logic.shop;

import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.eva.android.widget.AListAdapter2;
import com.eva.android.widget.Action;
import com.eva.android.widget.WidgetUtils;
import com.eva.epc.common.util.CommonUtils;
import com.x52im.mall.MallGlobal;
import com.x52im.mall.Utility;
import com.x52im.mall.shop.dto.Device;
import com.x52im.mall.shop.dto.SODetail;
import com.x52im.rbchat.R;

import java.util.ArrayList;

/**
 * 订单确认：商品列表包装实现类.
 * 
 * <p>
 * 商品列表的数据模型就是严格来自于购物的数据模型，本类中任何对数量等的修改
 * 都将同步到购物车的数据模型中，那么可以认为本类列表的数据模型与购物车的
 * 数据模型是完全同步的.
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @version 1.0
 */
public abstract class OrderComfirmGoodsListWrapper
{
	private Activity parentActivity = null;

	/** 标签组件：商品数量 */
//	private TextView viewGoodTotalCount = null;
	/** 明细列表 */
	private ListView listView;
	/** 明细列表Adapter */
	private DetailListAdapter listAdapter;
	

	public OrderComfirmGoodsListWrapper(Activity parentActivity)
	{
		this.parentActivity = parentActivity;

		initViews();
		initListeners();
		
		// ** 说明：列表的数据在初始化时是不会调用 notifyDataSetChanged()方法的，所以在
		// **     初始化时显示调用一下，否则在初始化时界面上的商品总额是不会被更新上去的
		// 当列表中的数据模型发生改变时要调用的方法
		listDataOnChanged(MallGlobal.getMallProviderInstance(parentActivity).getRobotimeMall().getShopCarProvider().getGoodsAmount());
		//
		refreshGoodsTotalCount();
	}

	private void initViews()
	{
//		viewGoodTotalCount = (TextView) parentActivity.findViewById(R.id.common_mall_shop_layout_order_confirm_goods_totalGoodCount);
		listView = (ListView) parentActivity.findViewById(R.id.common_mall_shop_layout_order_confirm_goods_listView);
		listAdapter = new DetailListAdapter(parentActivity);
		listView.setAdapter(listAdapter);
//		Utility.setListViewHeightBasedOnChildren(listView);
	}

	private void initListeners()
	{
	}

	/**
	 * 返回当前订单中的商品明细.
	 * 
	 * @return
	 */
	public ArrayList<SODetail> getSODetail()
	{
		return listAdapter.getListData();
	}
	
	/**
	 * 返回商品总价（不含运费的）.
	 * <p>
	 * 因为本类中的商品列表数据模型与购物车中是严格一致的，
	 * 所以列表中的商品总价就是购物车中的商品总价.
	 * 
	 * @return
	 */
	public double getGoodsAmount()
	{
		return MallGlobal.getMallProviderInstance(parentActivity).getRobotimeMall().getShopCarProvider().getGoodsAmount();
	}

	/**
	 * 数据合法性检验，保证要提交到服务端的数据不为空.
	 * 
	 * @return
	 */
	public boolean isValid()
	{
		return getSODetail().size() > 0;
	}
	
	/**
	 * 更新商品总数量在Ui组件上的显示.
	 */
	private void refreshGoodsTotalCount()
	{
		// 更新商品总数量
//		viewGoodTotalCount.setText(String.valueOf(RobotimeMall.getMallProviderInstance(parentActivity).getRobotimeMall().getShopCarProvider().getGoodsCount()));
	}
	
	/**
	 * 当本列表中的数据发生改变时（通常是数量发生了改变）要调用的方法.
	 * 
	 * @param goodsAmount 当前购物车中（也即是当前订单明细）的总金额
	 */
	protected abstract void listDataOnChanged(double goodsAmount);

	/**
	 * 自定义明细列表的adapter类实现.
	 * 
	 * <p>
	 * item的数量不支持直接编辑，因为要监听它的文本改事件（TextWatch）时，会在列表的
	 * 数据更新、notifyDatasetChacned()等时机产生错乱，所以目前就取消了文本框内容的直
	 * 接编辑，以后或许可以考虑通过像DMKX里样弹出一个单独的面板。目前只能通过加、减按
	 * 钮实现数量的更改。
	 */
	private class DetailListAdapter extends AListAdapter2<SODetail>
	{
		/** 本值用于记住正在修改中的列表明细行索引值 */
		private int loction;

		/** 记录选中的ListView的行索引值以备后用（目前是在：单击、长按2类事件中保存了此索引值）.*/
		protected int selectedListViewIndex = -1;
		
		public DetailListAdapter(Activity context)
		{
			super(context, R.layout.common_mall_shop_layout_order_confirm_good_list_item);
		}

		//重写本方法，以便使用自定义的列表数据模型：使用全局静态变量，目的是无论Ui如何变化都保留上次的查询结果，
		//以方便用户查看，提高用户体验，这对查询类的功能比较有用哦。另注：AListAdapter里的列表数据模型列象名就是listData，
		//所以本类里要使用自已的对象则再也不能用listData哦，否则本方法里将错误地引用于AListAdapter里的listData
		//从而导致空指针异常（之前就是碰到了这样的问题，让人百思不得其解）.
		@Override//本方法只在父类AListAdapter的构造方法里被调用一次，所以一定要注意staticListData被实例化的时机
		protected ArrayList<SODetail> createListData()
		{
			//注意：不能使用与AListAdapter里默认的数据模型listData一样的名字哦，否则将错误地引用父类该对象从而导致空指针
			return MallGlobal.getMallProviderInstance(parentActivity).getRobotimeMall().getShopCarProvider().getGoodsInCar();
		}

		@Override
		public View getView(final int position, View convertView, ViewGroup parent)
		{
			//列表item上的：商品图片
			ImageView viewGoodPic = null;
			//列表item上的：商品简称
			TextView viewGoodName = null;
			//列表item上的：使用性别
			TextView viewGender = null;
			//列表item上的：商品描述
			TextView viewGoodDesc = null;
			//列表item上的：订购数据
			EditText viewQuantity = null;
			//列表item上的：订购价格货币类型
			TextView viewPriceCurrency = null;
			//列表item上的：订购价格
			TextView viewPrice = null;
//			//列表item上的：订购金额货币类型
//			TextView viewAmountCurrency = null;
//			//列表item上的：订购金额小计
//			TextView viewTotalAmount = null;
			//列表item上的：商品的颜色
			TextView viewGoodColorDesc = null;
			//列表item上的：增加按钮 
			View btnAdd = null;
			//列表item上的：减少按钮 
			View btnReduce = null;
			
			Button btnDelete = null;

			//---------------------------------------------------------------------------------------- （1）UI初始化
			//当的item布局实例已经存在（不在存，意味着这个item刚好从不可见区移到可见区时）
			//** 根据android的列表ui实现，为了节比资源占用，假如列表有100行而可见区显示5行，那么任何时候
			//** 这个列表中只会有5个item的UI存在，其它的item都是当被转到可见区时自动把自
			//** 已的数据实时地更新列UI上，以便查看，也就是说item的UI并不是与后台数据一
			//** 一对应的，所以正如API文档里说的，convertView并不能确保它总能按你的想法保持不为null
			boolean needCreateItem = (convertView == null);
			//正在操作的列表行的数据集
			final SODetail rowData = listData.get(position);
			if (needCreateItem)
				//明细item的UI实例化
				convertView = layoutInflater.inflate(itemResId, null);

			//item里的操作组件实例
			viewGoodPic = (ImageView) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_goodPicView);
			viewGoodName = (TextView) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_goodNameView);
			viewGender = (TextView) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_forSexView);
			viewGoodDesc = (TextView) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_goodDescView);
			viewQuantity = (EditText) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_quantityEdit);
			viewPriceCurrency = (TextView) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_goodPriceCurrencyView);
			viewPrice = (TextView) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_goodPriceView);
//			viewAmountCurrency = (TextView) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_goodTotalAmountCurrencyView);
//			viewTotalAmount = (TextView) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_goodTotalAmountView);
			viewGoodColorDesc = (TextView) convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_goodColorDescView);
			btnAdd =  convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_quantityPlusBtn);
			btnReduce =  convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_quantityReduceBtn);
			btnDelete = (Button)convertView.findViewById(R.id.common_mall_shop_layout_order_confirm_good_item_delBtn);

			//---------------------------------------------------------------------------------------- （2）增加事件处理器
			//各操作组件的事件监听器只需要在convertView被实例化时才需要重建（convertView需要被实例化
			//当然就意味着它上面的所有操作组件都已经重新新建了）
			//** 关于事件处理器的说明：事件处理器的增加其实可以不这么麻烦，直接每getView一次就给组件new一个处理器，
			//** 这样做的好处是简单，但显然存在资源浪费（每刷新一次view就新建监听器）。而现在的实现就跟Android的列表
			//** 实现原理一样，在切换到下一组item前，监听器永远只有一屏item的数量（刷新时只需要即时刷新对应item的数据到
			//** 它的监听器里），这样就节省了资源开销！
			if(needCreateItem)
			{
//				//*** 为数量文本框增加监听器
//				EditQuantityTextWatcher editListen = new EditQuantityTextWatcher();
//				viewQuantity.addTextChangedListener(editListen);
//				viewQuantity.setTag(editListen);

				//*** 为加减快捷按钮增加监听器
				ChangeQuantityClickListener addListen = new ChangeQuantityClickListener(viewQuantity, 1);
				btnAdd.setOnClickListener(addListen);
				btnAdd.setTag(addListen);
				//*** 
				ChangeQuantityClickListener reduceListen = new ChangeQuantityClickListener(viewQuantity, -1);
				btnReduce.setOnClickListener(reduceListen);
				btnReduce.setTag(reduceListen);
				
				DeleteOnClickListener deleteLIstener = new DeleteOnClickListener();
				btnDelete.setOnClickListener(deleteLIstener);
				btnDelete.setTag(deleteLIstener);
			}

			//---------------------------------------------------------------------------------------- （3）
			//给标签设置值，以供用户查看
			Device d = MallGlobal.getMallProviderInstance(parentActivity).getRobotimeMall().getGoodsProvider().getDeviceById(rowData.getDevice_id());
			viewGoodPic.setImageResource(Utility.getDefaultGoodPreviewIconRes(d.getDevice_short_name()));
			viewGoodName.setText(d.getDevice_short_name());
			viewGender.setText(d.getFor_sex().equals("1") ? R.string.common_general_male : R.string.common_general_female);
			viewGoodDesc.setText(d.getDevice_desc());
			viewQuantity.setText(rowData.getPurchase_quantity());
			viewPriceCurrency.setText(Utility.DEFAULT_CURRENCY_TYPE_NAME);
			viewPrice.setText(rowData.getPurchase_price());
//			viewAmountCurrency.setText(Utility.DEFAULT_CURRENCY_TYPE_NAME);
//			viewTotalAmount.setText(rowData.getPurchase_amount());
			viewGoodColorDesc.setText(rowData.getColor_desc());

			//** 确保每次item被刷新时都更新操作组件事件监听器中要记录的该item所对应的 列表的行索引号
			//** 这样就能很好地确保行索引号的正确性了
//			EditQuantityTextWatcher editListener = (EditQuantityTextWatcher) viewQuantity.getTag();
//			editListener.setPosition(position);
			ChangeQuantityClickListener reduceListener = (ChangeQuantityClickListener) btnReduce.getTag();
			reduceListener.setPosition(position);
			ChangeQuantityClickListener addListen = (ChangeQuantityClickListener) btnAdd.getTag();
			addListen.setPosition(position);

			DeleteOnClickListener deleteListener = (DeleteOnClickListener) btnDelete.getTag();
			deleteListener.setPosition(position);
			
			return convertView;
		}

		@SuppressWarnings("unused")
		public int getSelectedListViewIndex()
		{
			return selectedListViewIndex;
		}
		@SuppressWarnings("unused")
		public void setSelectedListViewIndex(int selectedListViewIndex)
		{
			this.selectedListViewIndex = selectedListViewIndex;
//			this.notifyDataSetChanged();
		}
		
		@Override
		public void notifyDataSetChanged()
		{
			super.notifyDataSetChanged();

			// 当列表中的数据模型发生改变时要调用的方法
			listDataOnChanged(MallGlobal.getMallProviderInstance(parentActivity).getRobotimeMall().getShopCarProvider().getGoodsAmount());
			
			// 更新商品总数量在UI上的显示
			refreshGoodsTotalCount();
			
//			Log.d("XXCCXXCC", "listData.hashCode()="+listData.hashCode()
//			+",getGoodsInCar().hashCode()="+_Utils.getShopCarProvider().getGoodsInCar().hashCode()
//			+"||listSL="+listData.get(loction).getPurchase_quantity()
//				+",carSL="+_Utils.getShopCarProvider()
//				.getGoodInCar(listData.get(loction).getDevice_id(), listData.get(loction).getColor_id()).getPurchase_quantity());
		}

//		/**
//		 * 购买数量文本框内容改变监听器.
//		 */
//		private class EditQuantityTextWatcher implements TextWatcher
//		{
//			private int position = 0;
//
//			@Override
//			public void beforeTextChanged(CharSequence s, int start, int count,int after){
//				//
//			}
//			@Override
//			public void onTextChanged(CharSequence s, int start, int before,int count){
//				//
//			}
//
//			@Override
//			public void afterTextChanged(Editable s)
//			{
//				loction = position;
//
//				// 在本次加减操作前的文本中的值
//				int newQuantity = CommonUtils.getIntValue(s.toString());
//				if(newQuantity <= 0)
//				{
////					WidgetUtils.showToast(parentActivity, "购买数量不允许小于1!", ToastType.WARN);
//					Log.d("XXCCXXCC", "购买数量不允许小于1!");
//					newQuantity = 1;
//				}
//
////				// 设置最新的购买数量到数据模型中
////				listData.get(loction).setPurchase_quantity(String.valueOf(newQuantity));
////				
//////				此列表的数据模型应该用Observer集合实现，否则更新这个模型是不能同步更新购物车的哦？？？！！！（因为列表的模型在初始化完成后
//////				就与购物车脱节了，也就导致了修改数量后，下面的总金额在下次进入activity时不能正常显示（实际上是购物车中的数据没有更新！！）
////				
////				// 更新数据模型中的金额小计
////				listData.get(loction).reCalculatorAmount();
//				refresh(listData.get(loction), newQuantity);
//				
//				Log.d("XXCCXXCC", "listData.hashCode()="+listData.hashCode()
//						+",getGoodsInCar().hashCode()="+_Utils.getShopCarProvider().getGoodsInCar().hashCode()
//						+"||listSL="+listData.get(loction).getPurchase_quantity()
//							+",carSL="+_Utils.getShopCarProvider()
//							.getGoodInCar(listData.get(loction).getDevice_id(), listData.get(loction).getColor_id()).getPurchase_quantity());
//
////				// 用模型中新更新完成的数据来刷新UI(此时的UI数量组件上的结果才是本次增减后的真正结果)
////				notifyDataSetChanged();
//			}
//
//			public void setPosition(int position)
//			{
//				this.position = position;
//			}
//		}
		
		/**
		 * 删除按钮事件监听器.
		 */
		private class DeleteOnClickListener implements View.OnClickListener
		{
			int position = 0;

			public void setPosition(int position)
			{
				this.position = position;
			}

			@Override
			public void onClick(View v)
			{
				WidgetUtils.areYouSure(layoutInflater.getContext(), parentActivity.getString(R.string.common_mall_shop_shop_car_sure_delete), new Action() {
					@Override public void actionPerformed(Object obj){
						removeItem(position);
					}
				});
			}
		}


		/**
		 * 加减数量按钮监听器.
		 */
		private class ChangeQuantityClickListener implements View.OnClickListener
		{
			private int position = 0;
			private int changeSl = 0;
			private EditText editNumber;

			public ChangeQuantityClickListener(EditText editNumber, int changeSl)
			{
				this.changeSl = changeSl;
				this.editNumber = editNumber;
			}

			public void setPosition(int position)
			{
				this.position = position;
			}

			@Override public void onClick(View v)
			{
				loction = position;
				// 在本次加减操作前的文本中的值
				int text = CommonUtils.getIntValue(editNumber.getText().toString());
				// 本次增减操作后的数量结果
				int result = text + changeSl;
				
				//大于0才更新
				if (result >0)
				{
//					// 把本次加减后的结果设置到数据模型中
					// 设置最新的购买数量到数据模型中
					listData.get(loction).setPurchase_quantity(String.valueOf(result));
					
					// 用模型中新更新完成的数据来刷新UI(此时的UI数量组件上的结果才是本次增减后的真正结果)
					notifyDataSetChanged();
				}
				else
					WidgetUtils.showToast(layoutInflater.getContext(), parentActivity.getString(R.string.common_mall_shop_order_confirm_good_list_count_validate), WidgetUtils.ToastType.ERROR);

			}
		}
	}
}